#include"chessdatabase.h"
#include <stdexcept>
#include <iostream>

ChessDatabase::ChessDatabase(const std::string& db_path) {
    if (sqlite3_open(db_path.c_str(), &db) != SQLITE_OK) {
        throw std::runtime_error("无法打开数据库: " + std::string(sqlite3_errmsg(db)));
    }
    create_table();
}

ChessDatabase::~ChessDatabase() {
    sqlite3_close(db);
}

// 序列化关键点
nlohmann::json ChessDatabase::serializeKeypoints(const std::vector<cv::KeyPoint>& keypoints) {
    nlohmann::json j;
    for (const auto& kp : keypoints) {
        j.push_back({
            {"x", kp.pt.x},
            {"y", kp.pt.y},
            {"size", kp.size},
            {"angle", kp.angle},
            {"response", kp.response},
            {"octave", kp.octave},
            {"class_id", kp.class_id}
        });
    }
    return j;
}

// 序列化描述子（将Mat转换为二进制字符串）
nlohmann::json ChessDatabase::serializeDescriptors(const cv::Mat& descriptors) {
    if (descriptors.empty()) return nullptr;
    
    std::vector<uchar> data;
    cv::imencode(".bin", descriptors, data);
    return nlohmann::json::binary(data);
}

// 反序列化关键点
std::vector<cv::KeyPoint> ChessDatabase::deserializeKeypoints(const nlohmann::json& j) {
    std::vector<cv::KeyPoint> keypoints;
    for (const auto& item : j) {
        cv::KeyPoint kp;
        kp.pt.x = item["x"];
        kp.pt.y = item["y"];
        kp.size = item["size"];
        kp.angle = item["angle"];
        kp.response = item["response"];
        kp.octave = item["octave"];
        kp.class_id = item["class_id"];
        keypoints.push_back(kp);
    }
    return keypoints;
}

// 反序列化描述子
cv::Mat ChessDatabase::deserializeDescriptors(const nlohmann::json& j) {
    if (j.is_null()) return cv::Mat();
    
    const auto& binary = j.get_binary();
    cv::Mat descriptors(cv::imdecode(cv::Mat(binary), cv::IMREAD_UNCHANGED));
    return descriptors;
}


void ChessDatabase::create_table() {
        const char* sql = R"(
            CREATE TABLE IF NOT EXISTS chess_pieces (
                num INTEGER PRIMARY KEY AUTOINCREMENT,
                x REAL NOT NULL,
                y REAL NOT NULL,
                color TEXT CHECK(color IN ('red', 'black')),
                type TEXT NOT NULL,
                hu1 REAL NOT NULL,
                hu2 REAL NOT NULL,
                hu3 REAL NOT NULL,
                hu4 REAL NOT NULL,
                hu5 REAL NOT NULL,
                hu6 REAL NOT NULL,
                hu7 REAL NOT NULL,
                area REAL NOT NULL,
                perimeter REAL NOT NULL,
                aspect_ratio REAL NOT NULL,
                zd1 REAL NOT NULL,
                zd2 REAL NOT NULL,
                zd3 REAL NOT NULL,
                sift_keypoints TEXT,    -- 存储JSON序列化的关键点
                sift_descriptors TEXT   -- 存储JSON序列化的描述子
            );
        )";
 
        char* errMsg = nullptr;
        if (sqlite3_exec(db, sql, nullptr, nullptr, &errMsg) != SQLITE_OK) {
            std::string error = "创建表失败: " + std::string(errMsg);
            sqlite3_free(errMsg);
            throw std::runtime_error(error);
        }
    }

    void ChessDatabase::addChessPiece(const ChessPiece& piece) {
        const char* sql = R"(
            INSERT INTO chess_pieces (
                x, y, color, type, 
                hu1, hu2, hu3, hu4, hu5, hu6, hu7,
                area, perimeter, aspect_ratio,
                zd1, zd2, zd3,
                sift_keypoints, sift_descriptors
            ) VALUES (
                ?, ?, ?, ?, 
                ?, ?, ?, ?, ?, ?, ?,
                ?, ?, ?,
                ?, ?, ?,
                ?, ?
            );
        )";
 
        sqlite3_stmt* stmt;
        if (sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr) != SQLITE_OK) {
            throw std::runtime_error("准备SQL语句失败");
        }
 
        // 绑定基础参数、Hu矩、几何特征和区域密度（与之前相同）
        sqlite3_bind_double(stmt, 1, piece.x);
        sqlite3_bind_double(stmt, 2, piece.y);
        sqlite3_bind_text(stmt, 3, piece.color.c_str(), -1, SQLITE_STATIC);
        sqlite3_bind_text(stmt, 4, piece.type.c_str(), -1, SQLITE_STATIC);
        for (int i = 0; i < 7; ++i) sqlite3_bind_double(stmt, 5 + i, piece.huMoments[i]);
        sqlite3_bind_double(stmt, 12, piece.area);
        sqlite3_bind_double(stmt, 13, piece.perimeter);
        sqlite3_bind_double(stmt, 14, piece.aspectRatio);
        for (int i = 0; i < 3; ++i) sqlite3_bind_double(stmt, 15 + i, piece.zoneDensity[i]);
 
        // 序列化并绑定SIFT特征
        nlohmann::json j_keypoints = serializeKeypoints(piece.siftKeypoints);
        nlohmann::json j_descriptors = serializeDescriptors(piece.siftDescriptors);
        std::string keypoints_str = j_keypoints.dump();
        std::string descriptors_str = j_descriptors.dump();
        sqlite3_bind_text(stmt, 18, keypoints_str.c_str(), -1, SQLITE_TRANSIENT);
        sqlite3_bind_text(stmt, 19, descriptors_str.c_str(), -1, SQLITE_TRANSIENT);
 
        if (sqlite3_step(stmt) != SQLITE_DONE) {
            sqlite3_finalize(stmt);
            throw std::runtime_error("插入数据失败: " + std::string(sqlite3_errmsg(db)));
        }
 
        sqlite3_finalize(stmt);
    }
 

    void ChessDatabase::printAllChessPieces() {
        const char* sql = "SELECT * FROM chess_pieces;";
        sqlite3_stmt* stmt;
 
        if (sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr) != SQLITE_OK) {
            throw std::runtime_error("准备查询语句失败: " + std::string(sqlite3_errmsg(db)));
        }
 
        try {
            while (sqlite3_step(stmt) == SQLITE_ROW) {
                // 解析基础字段、Hu矩、几何特征和区域密度（与之前相同）
                int num = sqlite3_column_int(stmt, 0);
                double x = sqlite3_column_double(stmt, 1);
                double y = sqlite3_column_double(stmt, 2);
                const char* color = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 3));
                const char* type = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 4));
                std::array<double, 7> huMoments;
                for (int i = 0; i < 7; ++i) huMoments[i] = sqlite3_column_double(stmt, 5 + i);
                double area = sqlite3_column_double(stmt, 12);
                double perimeter = sqlite3_column_double(stmt, 13);
                double aspectRatio = sqlite3_column_double(stmt, 14);
                std::array<double, 3> zoneDensity;
                for (int i = 0; i < 3; ++i) zoneDensity[i] = sqlite3_column_double(stmt, 15 + i);
 
                // 解析SIFT特征
                const char* keypointsJson = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 18));
                const char* descriptorsJson = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 19));
                std::vector<cv::KeyPoint> siftKeypoints;
                cv::Mat siftDescriptors;
                if (keypointsJson != nullptr) {
                    try {
                        siftKeypoints = deserializeKeypoints(nlohmann::json::parse(keypointsJson));
                    } catch (const nlohmann::json::exception& e) {
                        std::cerr << "JSON解析关键点错误: " << e.what() << std::endl;
                    }
                }
                if (descriptorsJson != nullptr) {
                    try {
                        siftDescriptors = deserializeDescriptors(nlohmann::json::parse(descriptorsJson));
                    } catch (const nlohmann::json::exception& e) {
                        std::cerr << "JSON解析描述子错误: " << e.what() << std::endl;
                    }
                }
 
                // 打印所有字段（包括SIFT特征）
                std::cout << "----------------------------------------\n";
                std::cout << "编号: " << num
                          << " | 坐标: (" << x << ", " << y << ")"
                          << " | 颜色: " << color
                          << " | 类型: " << type << "\n";
                std::cout << "Hu矩: ";
                for (double hu : huMoments) std::cout << hu << " ";
                std::cout << "\n几何特征: 面积=" << area
                          << " 周长=" << perimeter
                          << " 宽高比=" << aspectRatio << "\n";
                std::cout << "\n区域密度: ";
                for (double zd : zoneDensity) std::cout << zd << " ";
                std::cout << "\nSIFT关键点数量: " << siftKeypoints.size();
                std::cout << "\nSIFT描述子维度: " << (siftDescriptors.empty() ? 0 : siftDescriptors.cols) << std::endl;
                std::cout << "----------------------------------------\n";
            }
        } catch (...) {
            sqlite3_finalize(stmt);
            throw;
        }
        sqlite3_finalize(stmt);
    }
